<template>
	<jk-dialog
		v-model="showModal"
		title="菜单分配"
		:disable-confirm-btn="disabledConfirmBtn"
		:confirm-btn-loading="confirmButtonLoading"
		:show-content-loading="contentLoading"
		@on-visible-change="onVisibleChange"
		@on-cancel="onVisibleChange(false)"
		@on-confirm="onConfirmOfDialog"
	>
		<div class="avatar-info">
			<el-avatar size="medium" icon="el-icon-user-solid"></el-avatar>
			<span class="">{{ targetName }}</span>
		</div>
		<div class="all-check-box">
			<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange">全选</el-checkbox>
		</div>
		<div class="permission-box">
			<div class="permission-box-inner">
				<el-tree
					ref="tree"
					:data="treeData"
					show-checkbox
					node-key="id"
					:props="defaultProps"
					default-expand-all
					:default-checked-keys="treeCheckIds"
					@check="onCheckChange"
				/>
			</div>
		</div>
	</jk-dialog>
</template>

<script>
    import { createTree } from '../../../utils/jk/jk-tool';
    import { getRouters } from '../../../api/menu';
    import { adminApiSystemUserAssignMenu, systemUserListUserMenus } from '../../../api/system/permission';
    import { listSimpleMenus } from '../../../api/system/menu';
    export default {
        name: 'SetModuleDialog',
        props: {
            dialogState: {
                type: Boolean,
                default: false
            },
            targetName: {
                type: String,
                default: null
            },
            dataId: {
                type: Number,
                default: null
            }
        },
        data() {
            return {
                contentLoading: false,
                menuData: [],
                isIndeterminate: true,
                checkAll: false,
                confirmButtonLoading: false,
                disabledConfirmBtn: false,
                showModal: false,
                treeData: [],
                defaultProps: {
                    children: 'children',
                    label: 'name'
                },
                treeCheckIds: [],
                roleMenuIds: [],
                userMenuIds: [],
                notCheck: [],
                notCheckFather: []
            };
        },
        watch: {
            dialogState(newVal) {
                this.showModal = newVal;
                if (newVal) {
                    this.treeCheckIds = [];
                    this.treeData = [];
                    this.showModal = true;
                    this.getDependentDataRequest();
                }
            }
        },
        methods: {
            handleCheckAllChange(e) {
                const cpTreeData = JSON.parse(JSON.stringify(this.treeData));
                this.treeData = [];
                if (e) {
                    this.treeCheckIds = this.menuData.map(x => x.id);
                } else {
                    this.treeCheckIds = [];
                }
                this.$nextTick(() => {
                    this.treeData = cpTreeData;
                });
                this.isIndeterminate = false;
            },
            onCheckChange(e, nodeObj) {
                this.treeCheckIds = nodeObj.checkedKeys;
                this.setAllCheckState(nodeObj.checkedKeys, this.menuData);
            },
            onConfirmOfDialog() {
                this.confirmButtonLoading = true;
                const menuIds = [];
                this.menuData.forEach(moduleItem => {
                    if (moduleItem.disabled === false) {
                        this.treeCheckIds.forEach(checkItem => {
                            if (checkItem === moduleItem.id) {
                                menuIds.push(checkItem);
                            }
                        });
                    }
                });
                adminApiSystemUserAssignMenu({
                    userId: this.dataId,
                    menuIds: menuIds
                }).then(res => {
                    this.confirmButtonLoading = false;
                    this.disabledConfirmBtn = false;
                    if (res.data.status === 200) {
                        this.showModal = false;
                        this.$tipsBar(this, 'save');
                        this.$emit('on-confirm');
                    }
                });
            },
            onVisibleChange(e) {
                if (!e) {
                    this.treeCheckIds = [];
                }
                this.$emit('on-visible-change', e);
            },
            infiniteNotCheck(item) {
                if (item.isCheck) {
                    if (item.children && item.children.length) {
                        item.children.forEach(x => {
                            this.infiniteNotCheck(x);
                        });
                    }
                } else {
                    this.notCheck.push(item);
                }
            },
            getNodeIdPath(item) {
                this.menuData.forEach(x => {
                    if (item.parentId === x.id) {
                        this.notCheckFather.push(x.id);
                        if (x.parentId !== 0) {
                            this.getNodeIdPath(x);
                        }
                    }
                });
            },
            getCheckIds(item) {
                if (item.isCheck) this.treeCheckIds.push(item.id);
                if (item.children && item.children.length) {
                    item.children.forEach(x => {
                        this.getCheckIds(x);
                    });
                }
            },
            // 拉平数据
            recursionOnlyOneLevel(list) {
                list.forEach(x => {
                    x.isCheck = false;
                    const cpItem = JSON.parse(JSON.stringify(x));
                    delete cpItem.children;
                    this.menuData.push(cpItem);
                    if (x.children && x.children.length) {
                        this.recursionOnlyOneLevel(x.children);
                    }
                });
            },
            // 当前登录人的拥有模块列表
            getLoginUserMenuListRequest() {
                return listSimpleMenus().then(res => {
                    if (res.data.status === 200) {
                        this.menuData = [];
                        this.recursionOnlyOneLevel(res.data.res);
                    }
                });
            },
            // 分别获该用户独立授权的模块和所属角色授权的模块
            getPartUserMenuAndRoleMenuListRequest() {
                return systemUserListUserMenus(this.dataId).then(res => {
                    this.disabledConfirmBtn = false;
                    this.contentLoading = false;
                    if (res.data.status === 200) {
                        this.userMenuIds = res.data.res.userMenuIds;// 用户拥有的模块ids（不包含角色）
                        this.roleMenuIds = res.data.res.roleMenuIds;// 用户所属角色拥有的模块ids（不包括用户本身）
                        const originalCheckData = Array.from(new Set([...this.roleMenuIds, ...this.userMenuIds]));
                        this.menuData.forEach((item) => {
                            item.disabled = false;
                            // 禁用角色选中的模块
                            this.roleMenuIds.forEach((roleID) => {
                                if (item.id === roleID) item.disabled = true;
                            });
                            originalCheckData.forEach(x => {
                                if (item.id === x) item.isCheck = true;
                            });
                        });
                        // -----------解决tree组件中给勾选状态的节点创建一个子节点时，子节点错误的显示为勾选的问题----------------
                        this.treeData = createTree(this.menuData, {});
                        this.notCheck = [];
                        this.notCheckFather = [];
                        // 获取没有被勾选的节点ids
                        this.treeData.forEach(x => {
                            this.infiniteNotCheck(x);
                        });
                        // 获取没有被勾选的节点的父级及以上节点
                        this.notCheck.forEach(x => {
                            this.getNodeIdPath(x);
                        });
                        // 得到所有需要取消勾选的ids
                        const allNeedCancelCheck = [...this.notCheckFather.map(x => x), ...this.notCheck.map(x => x.id)];
                        this.menuData.forEach(x => {
                            allNeedCancelCheck.forEach(k => {
                                if (x.id === k) x.isCheck = false;
                            });
                        });
                        this.treeData = createTree(this.menuData, {});
                        this.treeCheckIds = [];
                        // 获取所有isCheck为true的集合作为tree默认勾选值
                        this.treeData.forEach(x => {
                            this.getCheckIds(x);
                        });
                        // --------------end-----------------
                        this.setAllCheckState(this.treeCheckIds, this.menuData);
                    }
                });
            },
            async getDependentDataRequest() {
                this.disabledConfirmBtn = true;
                this.contentLoading = true;
                await this.getLoginUserMenuListRequest();
                await this.getPartUserMenuAndRoleMenuListRequest();
            },
            setAllCheckState(checkIds, allModule) {
                if (!checkIds.length) {
                    this.isIndeterminate = false;
                    this.checkAll = false;
                } else if (checkIds.length === allModule.length) {
                    this.isIndeterminate = false;
                    this.checkAll = true;
                } else {
                    this.isIndeterminate = true;
                    this.checkAll = true;
                }
            }
        }
    };
</script>
<style scoped lang="scss">
.avatar-info {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    font-size: 14px;
}
.all-check-box {
    display: flex;
    margin-bottom: 6px;
    justify-content: space-between;
    align-items: flex-end;
    .selected-count {
        font-size: 16px;
        font-weight: 700;
    }
}
.module-target-name {
    margin-left: 4px;
}
</style>
